import { EntityInfo, EntityPartType } from '@amcax/web-render';
import { FieldProps } from '@rjsf/utils';
import { Flex, Select } from 'antd';
import { MessageContext, userEvents } from 'nextcae-base';
import { useFocusStore } from 'nextcae-base/src/common/store';
import { useContext, useEffect, useState } from 'react';
import { ColorMap, FormatType } from '@/components/PickCopy/type';
import PickIcon from './PickIcon';
import styles from './styles.module.scss';
import { pickManager } from '@/components/PickCopy/PickManager';
import { EventNum } from 'nextcae-base/src/types/event';
import { EntityTitleMap } from '@/common/types/command/types';

const { Option } = Select;
/**
 * 通过控制拾取类型，从渲染场景中拾取Entity，并通过onChange返回Entity信息数组
 */
export function SelectionPickField({
  schema,
  idSchema,
  uiSchema,
  disabled,
  formData,
  onChange,
}: FieldProps) {
  const {
    focusId,
    allPickIds,
    addPickId,
    removePickId,
    setFocused,
    next,
    clear,
  } = useFocusStore();
  const { layout: layout1, labelW: labelW2 } = useContext(MessageContext);
  // 是否激活该PickField，激活时拾取到的数据都到该字段
  const [active, setActive] = useState(false);
  // 切换拾取类型的选项
  const [options, setOptions] = useState<FormatType[]>([]);
  // 当前拾取类型
  const [currentPickType, setCurrentPickType] = useState<EntityPartType>(null);

  const labelW = labelW2 ?? 'max-content';
  const layout = uiSchema?.['ui:layout'] ?? layout1 ?? [1, 1];
  const focused = uiSchema?.['ui:focused'] ?? false;
  const xOptions = schema?.['x-options'];
  const isNext = schema?.['isNext'] ?? true;
  const [color, setColor] = useState<{ [key: string]: number }>(
    uiSchema?.['ui:color'] ?? null,
  );
  const isMultiPick = !(schema.maxItems === 1);

  const fieldId = idSchema.$id;

  // 初始化，创建Interactor等
  useEffect(() => {
    addPickId(fieldId); // 收集所有的需要pick的id
    // 注册pick
    pickManager().getPickSelect().registerEvents();
    pickManager().setPickStatus('cmd'); // 设置选择器类型
    // 默认选中
    if (focused) {
      setFocused(fieldId);
    }
    userEvents.on(EventNum.All_SELECT_ENTS, setFormatData);
    return () => {
      removePickId(fieldId);
      if (allPickIds.length === 0) {
        userEvents.off(EventNum.All_SELECT_ENTS, setFormatData);
        pickManager().cmdExit(); // 退出
        clear();
      } else {
        pickManager().getPickSelect().setEntsSelected(false, fieldId, true);
        setFocused(allPickIds[0]);
      }
    };
  }, []);
  // 更新拾取类型的下拉框选项列表
  useEffect(() => {
    const opts: FormatType[] = [];
    const temp = xOptions;
    // options 的格式应该支持两种:
    // 1. 字符串数组：['point', 'line', 'face']，对应到EntityPartType的类型字符串
    // 2. 对象数组：[{'title':'顶点', const:'point'}]，title可以自定义显示的文本，const取值同上
    // 转换为 FormatType[] 格式
    if (!Array.isArray(temp)) {
      // TODO 显示错误，ui:options必须有options，且options必须是数组
    } else if (temp.length === 0) {
      // TODO options 不能为空数组
    } else if (typeof temp[0] === 'string') {
      // 1. 字符串数组：['point', 'line', 'face']，对应到EntityPartType的类型字符串
      const unsupportTypes: string[] = []; // 不支持的类型类别
      for (const item of temp) {
        const type = EntityPartType[item as keyof typeof EntityPartType];
        if (type === undefined) {
          unsupportTypes.push(item);
          continue;
        }
        opts.push({ title: EntityTitleMap[type], entityPartType: type });
      }
      if (unsupportTypes.length > 0) {
        // TODO 显示错误，不支持的types
      }
    } else if (temp[0].title !== undefined && temp[0].const !== undefined) {
      // 2. 对象数组：[{'title':'顶点', const:'point'}]，title可以自定义显示的文本，const对应到EntityPartType的类型字符串
      const opts: FormatType[] = [];
      const unsupportTypes: string[] = []; // 不支持的类型类别
      for (const item of temp) {
        const type = EntityPartType[item.const as keyof typeof EntityPartType];
        if (type === undefined) {
          unsupportTypes.push(item.const);
          continue;
        }
        opts.push({ title: item.title, entityPartType: type });
      }
      if (unsupportTypes.length > 0) {
        // TODO 显示错误，不支持的types
      }
    } else {
      // TODO 显示错误，不支持的options类型
    }
    // 检查是否和options完全一样，不完全一样才重新赋值；默认不存在重复的
    const allSame =
      options.length === opts.length &&
      options.every(
        (option) =>
          opts.findIndex(
            (opt) =>
              opt.title === option.title &&
              opt.entityPartType === option.entityPartType,
          ) >= 0,
      );
    if (!allSame) {
      setCurrentPickType(opts[0].entityPartType);
      pickManager().setCmdPickType(opts[0].entityPartType);
      if (options.length > 0) {
        // 不是初次加载（options不为空），才清空数据
        onChange([]);
      }
      setOptions(opts);
    }
  }, [xOptions]);
  // 监听focusId变化，设置当前PickField是否激活
  useEffect(() => {
    const focused = fieldId === focusId;
    setActive(focused);
  }, [focusId]);
  // 监听disabled变化，是否启用禁用当前的拾取
  useEffect(() => {
    if (disabled) {
      // 取消选中
      pickManager().getPickSelect().setEntsSelected(false, fieldId);
    } else {
      pickManager().setColor(color);
      pickManager().getPickSelect().setEntsSelected(true, fieldId);
    }
  }, [disabled]);
  // 监听allPickIds 和 pick 类型的变化，并根据顺序，来设置选中后的颜色
  useEffect(() => {
    if (active) {
      let colorTemp = color;
      if (!color) {
        const indx = allPickIds.findIndex((item) => item === fieldId);
        const color = ColorMap[currentPickType]?.[indx];
        indx > -1 && (colorTemp = { [currentPickType]: +color });
      }
      setColor(colorTemp);
      pickManager().setColor(colorTemp);
    }
  }, [allPickIds, currentPickType, active]);
  // 判断下拉选中的pick类型是不是多选
  useEffect(() => {
    if (currentPickType && active) {
      pickManager().setCmdPickType(currentPickType);
    }
  }, [currentPickType, active]);
  // 如果不能多选，则清空数据
  useEffect(() => {
    if (active && !isMultiPick) {
      onChange([]);
    }
  }, [active, isMultiPick]);
  // 当激活状态，isMultiPick变化时，重新设置是否能框选，
  useEffect(() => {
    if (active) {
      pickManager().enableBoxSelect = isMultiPick;
      pickManager().getPickSelect().isMultiPick = isMultiPick;
    }
  }, [active, isMultiPick, disabled]);

  // 监听formData的变化，更新多个地方的拾取信息（TODO 待优化）
  useEffect(() => {
    if (formData) {
      if (formData?.length === 0) {
        pickManager()
          .getPickSelect()
          .setEntsSelected(false, fieldId, true, formData);
      } else {
        setCurrentPickType((state) => formData[0]?.type ?? state);
        pickManager()
          .getPickSelect()
          .setEntsSelected(true, fieldId, true, formData);
      }
    }
  }, [formData]);

  function setFormatData(data: {
    selectedEnts: EntityInfo[];
    focusId: string;
  }) {
    if (fieldId === data.focusId) {
      onChange(data.selectedEnts);
      !isMultiPick && isNext && next();
    }
  }
  const fontSize = 12;
  // 点击选中
  const clickSetFocus = () => {
    setFocused(fieldId);
    onChange([]);
  };
  return (
    <Flex style={{ gap: 4, marginBottom: 4 }}>
      <Flex style={{ width: labelW, flex: layout[0] }}>
        <span style={{ flex: 1, fontSize }}>{schema.title}</span>
        <PickIcon
          disabled={disabled}
          active={active}
          onClick={() => clickSetFocus()}
        />
      </Flex>
      <Flex style={{ gap: '4px', flex: layout[1], fontSize }}>
        {options.length > 1 ? (
          <Select
            style={{ width: '100%' }}
            styles={{ popup: { root: { borderRadius: '4px' } } }}
            value={currentPickType}
            onChange={(value) => {
              clickSetFocus();
              setCurrentPickType(value);
            }}>
            {options.map((item) => (
              <Option
                key={item.entityPartType}
                className={styles._select_option}
                value={item.entityPartType}>
                {item.title}
              </Option>
            ))}
          </Select>
        ) : (
          <>{'请选择' + options[0]?.title}</>
        )}
      </Flex>
    </Flex>
  );
}
